package com.hzgj.bcl.soa.api;

import com.hzgj.bcl.concurrent.FutureListener;
import com.hzgj.bcl.soa.config.ReferenceDef;
import com.hzgj.bcl.soa.rpc.RpcDispatcher;

import java.lang.reflect.Proxy;

public class ProxyFactory {

    private static ProxyFactory instane = new ProxyFactory();

    private ProxyFactory() {
    }

    public static ProxyFactory getInstance() {
        return instane;
    }

    public static <T> ObjProxyBuilder<T> proxyBuilder(Class<T> clazz) {
        return new ObjProxyBuilder<T>(clazz);
    }

    public static class ObjProxyBuilder<T> {
        private Class<T> clazz;
        private RpcDispatcher rpcDispatcher;
        private ReferenceDef referenceDef;
        private FutureListener<?> futureListener;

        public ObjProxyBuilder(Class<T> clazz) {
            this.clazz = clazz;
        }

        public ObjProxyBuilder<T> dispatch(RpcDispatcher rpcDispatcher) {
            this.rpcDispatcher = rpcDispatcher;
            return this;
        }

        public ObjProxyBuilder<T> futureListener(FutureListener<?> futureListener) {
            this.futureListener = futureListener;
            return this;
        }

        public ObjProxyBuilder<T> referenceDef(ReferenceDef referenceDef) {
            this.referenceDef = referenceDef;
            return this;
        }

        public T build() {
            ObjectProxy<T> objectProxy = new ObjectProxy<T>();
            objectProxy.setReferenceDef(referenceDef);
            objectProxy.setFutureListener(futureListener);
            objectProxy.rpcDispatcher(rpcDispatcher);
            try {
                rpcDispatcher.start();
            } catch (Exception e) {
                rpcDispatcher.stop();
                throw new RuntimeException("start object Proxy failure.", e);
            }
            return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, objectProxy);
        }
    }
}


